#pragma once
#include <string>
#include <fstream>

#define debug(format,...) \
	Logger::getInstance()->log(Logger::DEBUG, __FILE__, __LINE__, format,##__VA_ARGS__);

#define info(format,...) \
	Logger::getInstance()->log(Logger::INFO, __FILE__, __LINE__, format,##__VA_ARGS__);

#define warn(format,...) \
	Logger::getInstance()->log(Logger::WARN, __FILE__, __LINE__, format,##__VA_ARGS__);

#define error(format,...) \
	Logger::getInstance()->log(Logger::ERROR, __FILE__, __LINE__, format,##__VA_ARGS__);

#define fatal(format,...) \
	Logger::getInstance()->log(Logger::FATAL, __FILE__, __LINE__, format,##__VA_ARGS__);

class Logger
{
public:
	enum Level
	{
		DEBUG = 0,
		INFO,
		WARN,
		ERROR,
		FATAL,
		LEVEL_COUNT
	};

	static Logger* getInstance();

	void log(Level level, const char* file, int line, const char* format, ...);

	void level(Level level);

	void max(int bytes);

	void open(const std::string& filename);

	void close();

	~Logger();

private:
	Logger();
	Logger(const Logger&) = delete;
	Logger& operator=(const Logger&) = delete;
	void rotate();

private:
	std::string m_filename;
	std::ofstream m_fout;
	Level m_level;
	int m_max;
	int m_len;
	static const char* s_level[LEVEL_COUNT];
};